
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using UIOC;

namespace KuiHuaBaoDian.Extensions {

    public static class RuntimeExtension {

        public static UniTask Delay(this IRuntime runtime,
            int millisecondsDelay,
            bool ignoreTimeScale = false,
            PlayerLoopTiming delayTiming = PlayerLoopTiming.Update,
            CancellationToken cancellationToken = default
        ) {
            UnityEngine.Assertions.Assert.IsNotNull(runtime);
            UnityEngine.Assertions.Assert.IsTrue(millisecondsDelay >= 0);

            return UniTask.Delay(
                millisecondsDelay: millisecondsDelay,
                ignoreTimeScale: ignoreTimeScale,
                delayTiming: delayTiming,
                cancellationToken: cancellationToken,
                cancelImmediately: true
            ).AttachExternalCancellation(runtime.QuitCancellationToken).SuppressCancellationThrow();
        }

        public static async UniTask WaitUntil(this IRuntime runtime,
            Func<bool> predicate,
            PlayerLoopTiming timing = PlayerLoopTiming.Update,
            CancellationToken cancellationToken = default
        ) {
            UnityEngine.Assertions.Assert.IsNotNull(runtime);
            UnityEngine.Assertions.Assert.IsNotNull(predicate);

            await UniTask.WaitUntil(
                predicate: predicate,
                timing: timing,
                cancellationToken: cancellationToken,
                cancelImmediately: true
            ).AttachExternalCancellation(runtime.QuitCancellationToken).SuppressCancellationThrow();
        }

        public static UniTask WaitWhile(this IRuntime runtime,
            Func<bool> predicate,
            PlayerLoopTiming timing = PlayerLoopTiming.Update,
            CancellationToken cancellationToken = default
        ) {
            UnityEngine.Assertions.Assert.IsNotNull(predicate);
            return UniTask.WaitWhile(
                predicate: predicate,
                timing: timing,
                cancellationToken: cancellationToken,
                cancelImmediately: true
            ).AttachExternalCancellation(runtime.QuitCancellationToken).SuppressCancellationThrow();
        }
    }
}
